package protocol

import (
	"encoding/json"
)

// Method represents the China E-Port UKey methods
type Method string

const (
	MethodGetCertNo           Method = "cus-sec_SpcGetCertNo"
	MethodGetEntName          Method = "cus-sec_SpcGetEntName"
	MethodGetEnvCertAsPEM     Method = "cus-sec_SpcGetEnvCertAsPEM"
	MethodGetSignCertAsPEM    Method = "cus-sec_SpcGetSignCertAsPEM"
	MethodSHA1DigestAsPEM     Method = "cus-sec_SpcSHA1DigestAsPEM"
	MethodSignDataAsPEM       Method = "cus-sec_SpcSignDataAsPEM"
	MethodSignDataNoHashAsPEM Method = "cus-sec_SpcSignDataNoHashAsPEM"
)

// Request represents the protocol request to China E-Port
type Request struct {
	ID     int         `json:"_id"`
	Method Method      `json:"_method"`
	Args   interface{} `json:"args"`
}

// Response represents the protocol response from China E-Port
type Response struct {
	ID     int          `json:"_id"`
	Method Method       `json:"_method"`
	Status string       `json:"_status"`
	Args   ResponseArgs `json:"_args"`
}

// ResponseArgs represents the response arguments structure
type ResponseArgs struct {
	Result bool          `json:"Result"`
	Data   []interface{} `json:"Data"`
	Error  []string      `json:"Error"`
}

// NewRequest creates a new protocol request with proper args handling
func NewRequest(id int, method Method, args interface{}) *Request {
	// Ensure args is always an object, never nil
	if args == nil {
		args = struct{}{}
	}

	return &Request{
		ID:     id,
		Method: method,
		Args:   args,
	}
}

// Marshal encodes the request to JSON with proper formatting
func (r *Request) Marshal() ([]byte, error) {
	// Ensure args is always an object
	if r.Args == nil {
		r.Args = struct{}{}
	}

	return json.Marshal(r)
}

// InDataArgs represents arguments for methods that require inData
type InDataArgs struct {
	InData string `json:"inData"`
}

// SzInfoArgs represents arguments for SHA1 digest method
type SzInfoArgs struct {
	SzInfo string `json:"szInfo"`
}
